package com.hxgis.common.service.impl;

import com.es.common.EsAggCondition;
import com.es.common.domain.EsCondition;
import com.es.common.domain.agg.Group;
import com.es.wrapper.DataWrapper;
import com.hxgis.common.base.StationCache;
import com.hxgis.common.dto.AreaInfoDTO;
import com.hxgis.common.dto.StationInfoDTO;
import com.hxgis.common.entity.RainstormInfo;
import com.hxgis.common.entity.Station;
import com.hxgis.common.entity.StationDistance200;
import com.hxgis.common.repository.StationDistance200Repository;
import com.hxgis.common.repository.StationInfoRepository;
import com.hxgis.common.service.StationService;
import com.hxgis.common.utils.CollectionUtils;
import com.hxgis.common.utils.DistanceUtil;
import com.hxgis.common.utils.GridUtil;
import com.hxgis.common.utils.quickhull.datastructures.LinkedList;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.awt.geom.Point2D;

import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service
public class StationServiceImpl implements StationService {

    @Autowired
    StationInfoRepository stationInfoRepository;

    @Autowired
    StationDistance200Repository stationDistance200Repository;

    @Override
    public void initDistance200ToEs() {
        EsCondition esCondition = EsCondition.getEsCondition();
        esCondition.size(10000);
        List<Station> stations = stationInfoRepository.selectList(esCondition);
        List<StationDistance200> stationDistance200s = new ArrayList<>();
        for (int i = 0; i < stations.size(); i++) {
            StationDistance200 stationDistance200 = new StationDistance200();
            Station station_pre = stations.get(i);
            boolean flag = false;
            StringBuffer stringBuffer = new StringBuffer();
            for (int j = 0;j < stations.size(); ++j){

                Station station_old = stations.get(j);
                double distance = DistanceUtil.countDistance(Double.valueOf(station_pre.getLon()), Double.valueOf(station_pre.getLat())
                        , Double.valueOf(station_old.getLon()), Double.valueOf(station_old.getLat()));
                if (Double.doubleToLongBits(distance) < Double.doubleToLongBits(200)){
                    stringBuffer.append(station_old.getStationNo()).append(",");
                    flag = true;
                }
            }
            stationDistance200.setStationNo(station_pre.getStationNo());
            stationDistance200.setDistanceStations(stringBuffer.toString());
            stationDistance200s.add(stationDistance200);
            if (!flag) break;
        }
        stationDistance200Repository.saveBatch(stationDistance200s);
    }

    @Override
    public List<Station> selectAll() {
        EsCondition esCondition = EsCondition.getEsCondition();
        esCondition.size(10000);
        return stationInfoRepository.selectList(esCondition);
    }

    @Override
    public Map<String, StationDistance200> queryAllStation200() {
        EsCondition esCondition1 = EsCondition.getEsCondition();
        esCondition1.size(10000);
        List<StationDistance200> stationDistance200s = stationDistance200Repository.selectList(esCondition1);
        Map<String, StationDistance200> collect =
                stationDistance200s.stream().collect(Collectors.toMap(StationDistance200::getStationNo, value -> value));
        return collect;
    }

    @Override
    public Map<String, Station> queryAllStation() {
        EsCondition esCondition = EsCondition.getEsCondition();
        esCondition.size(10000);
        List<Station> stationList = stationInfoRepository.selectList(esCondition);
        Map<String, Station> stationMap = stationList.stream().collect(Collectors.toMap(Station::getStationNo, k -> k));
        return stationMap;
    }

    @Override
    public Map<String, LinkedList> queryAllStationAffect() {
        Map<String, LinkedList> map = new HashMap<>();
        EsCondition esCondition = EsCondition.getEsCondition();
        esCondition.size(10000);
        List<Station> stationList = stationInfoRepository.selectList(esCondition);
        stationList.stream().forEach(x -> {
            LinkedList pointSet = new LinkedList();
            String[] split = x.getBound().split(";");
            Arrays.stream(split).forEach(y -> {
                String[] split1 = y.split(",");
                pointSet.insert(new Point2D.Double(Double.valueOf(split1[0]),Double.valueOf(split1[1])));
            });
            map.put(x.getStationNo(),pointSet);

        });
        return map;
    }

    @Override
    public double[] getCenter(List<RainstormInfo> rainstormInfos) {
        List<String> stationIds = rainstormInfos.stream().map(x -> x.getStationNo()).collect(Collectors.toList());
        EsCondition stationCondition = EsCondition.getEsCondition();
        stationCondition.in("stationNo", CollectionUtils.convertCollectionString(stationIds));
        stationCondition.size(10000);
        List<Station> stations = stationInfoRepository.selectList(stationCondition);
        List<Double> latLists = stations.stream().map(u -> Double.parseDouble(u.getLat())).collect(Collectors.toList());
        List<Double> lonLists = stations.stream().map(u -> Double.parseDouble(u.getLon())).collect(Collectors.toList());
        double[] lons = new double[lonLists.size()];
        double[] lats = new double[latLists.size()];
        for (int i = 0; i < latLists.size(); i++) {
            lats[i] = latLists.get(i);
        }
        for (int i = 0; i < lonLists.size(); i++) {
            lons[i] = lonLists.get(i);
        }
        return GridUtil.centroidOfPolygon(lats,lons);
    }


    /**
     * 获取省市基础信息
     */
    @Override
    public Map<String, List<AreaInfoDTO>> getProvinceInfo() {
        long st = System.currentTimeMillis();
        EsAggCondition esAggCondition = EsAggCondition.getInstance();
        Group provinceGroup = esAggCondition.Group("province");
        provinceGroup.size(100);
        Group cityGroup = provinceGroup.groupSub("city");
        cityGroup.size(500);
        EsCondition condition = esAggCondition.getCondition().size(5000);
        List<AreaInfoDTO> areaInfoDTOList = stationInfoRepository.selectListAgg(esAggCondition, new DataWrapper<AreaInfoDTO>() {
            @Override
            public AreaInfoDTO wrapper(Map<String, Object> data) {
                AreaInfoDTO areaInfoDTO = new AreaInfoDTO();
                areaInfoDTO.setProvince(data.get("province").toString());
                areaInfoDTO.setCity(data.get("city").toString());
                return areaInfoDTO;
            }
        });
        Map<String, List<AreaInfoDTO>> areaInfosMap = areaInfoDTOList.stream().collect(Collectors.groupingBy(AreaInfoDTO::getProvince));
        log.info("查询基础信息es用时{}",System.currentTimeMillis() - st);
        return areaInfosMap;
    }

    /**
     * 查询所有站点信息
     * @return
     */
    @Override
    public List<StationInfoDTO> getAllStation() {
        List<Station> stations = StationCache.getStations();
        return stations.stream().map(x -> {
            StationInfoDTO stationInfoDTO = new StationInfoDTO();
            BeanUtils.copyProperties(x,stationInfoDTO);
            return stationInfoDTO;
        }).collect(Collectors.toList());
    }
}
